package com.okbihuo.perm.component.sms.logic;


import com.okbihuo.perm.component.sms.domain.Sms;
import com.okbihuo.perm.component.sms.logic.type.SmsType;
import com.okbihuo.perm.component.sms.logic.vo.SmsRecallVO;
import com.okbihuo.perm.component.sms.service.SmsService;
import com.okbihuo.perm.component.sms.utils.JuHeSmsUtils;
import com.okbihuo.perm.constants.SystemCode;
import com.okbihuo.perm.core.tool.api.BaseException;
import com.okbihuo.perm.core.tool.api.ResultCode;
import com.okbihuo.perm.core.tool.jackson.JsonUtil;
import com.okbihuo.perm.core.tool.utils.RandomType;
import com.okbihuo.perm.core.tool.utils.RegexUtil;
import com.okbihuo.perm.core.tool.utils.StringUtil;
import com.okbihuo.perm.modules.auth.UserDetailServiceImpl;
import com.okbihuo.perm.modules.rwb.sys.domain.RwbSystemSetting;
import com.okbihuo.perm.modules.rwb.sys.service.RwbSystemSettingService;
import lombok.extern.java.Log;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.List;

/**
 * 短信逻辑
 * @author stt
 */
@Component
@Log
public class SmsLogic {

    @Autowired
    private SmsService smsService;
    @Autowired
    private RwbSystemSettingService systemSettingService;
    @Autowired
    private UserDetailServiceImpl userService;

    /**
     * 发送短信验证
     * @param mobile
     * @param tplId
     * @param ip
     * @param type
     * @return
     * @throws BaseException
     */
    public boolean sendSMS(String mobile, String tplId, String ip, SmsType type) throws BaseException {
        //验证手机格式
        boolean match = RegexUtil.match(RegexUtil.PHONE, mobile);
        if(!match){
            throw new BaseException(ResultCode.FAILURE,"手机号已注册，请直接登陆");
        }
        //验证之前是否注册过
        final UserDetails byPhone = userService.getByPhone(mobile);
        if(SmsType.REGISTER.equals(type)){
            if (byPhone!=null){
                throw new BaseException(ResultCode.FAILURE,"手机号已注册，请直接登陆");
            }
        }
        if(SmsType.RESET_PASSWORD.equals(type)){
            if(byPhone==null){
                throw new BaseException(ResultCode.FAILURE,"当前手机号未注册!");
            }
        }
        //获取系统设置的发送短信次数
        RwbSystemSetting smsCount = systemSettingService.getByCode(SystemCode.smsCount);
        List<Sms> listByIpWithToday = smsService.listByIpWithToday(ip);
        if(listByIpWithToday.size() > Integer.valueOf(smsCount.getValue())){
            throw new BaseException(ResultCode.FAILURE,"今日短信次数已用完!");
        }
        return toSend(mobile,tplId,ip,type);
    }


    /**
     * 真实发送短信
     * @param mobile
     * @param tplId
     * @param ip
     * @param type
     * @return
     * @throws BaseException
     */
    public boolean toSend(String mobile, String tplId, String ip, SmsType type) throws BaseException {
        boolean flag = false;
        // 生成验证码
        String ranDomNum = StringUtil.random(6, RandomType.INT);
        // 构造聚合需要的tpl_value
        String tplValue = "#code#=" + ranDomNum;
        //获取系统设置的短信超期时间
        RwbSystemSetting smsExpiresAt = systemSettingService.getByCode(SystemCode.smsExpiresAt);
        //当前时间加上数据库设置的超期时间(分钟)转换成时间戳
        Long expired = LocalDateTime.now().plusMinutes(Integer.valueOf(smsExpiresAt.getValue())).toInstant(ZoneOffset.of("+8")).toEpochMilli();
        //保存短信发送存根
        Sms sms = Sms.create(mobile,ranDomNum,ip,tplId,tplValue,type.name(),expired);
        sms = smsService.saveOrUpdateAndReturn(sms);
        // 发送数据
        try {
            // 发送数据给第三方API
            SmsRecallVO recallVO = JuHeSmsUtils.send(mobile, tplId, tplValue);
            String response = JsonUtil.toJson(recallVO);
            log.info(response);
            // 保存短信回执
            sms.setResponse(response);
            // 保存错误代码
            sms.setErrorCode(recallVO.getError_code());
            if (recallVO.getError_code() == 0) {
                sms.setSid(recallVO.getResult().getSid());
                flag = true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            smsService.saveOrUpdateAndReturn(sms);
        }
        return flag;
    }

}
